/*
 @Name: selecttree插件
 @Author: ray
 @License: MIT
*/
; rayui.define(["tree"], function (exports, undef) {
    "use strict";

    var $ = rayui.$,
        tree = rayui.tree,
        plugName = "selecttree",
        $win = $(window),
        $doc = $(document),
        globalIndex = 1000,
        dict = { X: -1 },
        isDocBindMouseEvent = false,
        dataCache = {
            mclass: {},
            datas: {}
        },
        globalOptions = {
            maxHeight: 240,
            fieldId: "id", //数据列
            fieldName: "name", //显示列
            fieldChildren: "children", //子节点
            showTextOnNoSelected: "请选择",
            animSpeed: 200//动画执行时间
        },
        DealClass = function (options) {
            var that = this;
            that.index = globalIndex;

            options.oElem = options.elem;
            options.oOnSelect = options.onSelect;
            options.multiple = options.multiple || $(options.oElem).prop("multiple");
            options = that.options = $.extend(true, {}, globalOptions, options);
            delete options.width;

            //格式化选中数据
            var selectedValues = options.selectedValues, vals = [];
            if (typeof selectedValues === "string" || typeof selectedValues === "number") {
                vals.push({ key: options.fieldId, value: selectedValues });
            } else if (Object.prototype.toString.call(selectedValues) == '[object Array]') {
                vals = selectedValues;
            } else if (typeof selectedValues === "object") {
                vals.push(selectedValues);
            }
            options.selectedValues = vals;

            DealClass.utils.init.call(that);
            DealClass.utils.addEvents.call(that);
            options.data && DealClass.utils.initSelectData.call(that);
        };

    DealClass.utils = {
        init: function () {
            var that = this,
                options = that.options;

            options.$main = $('<div class="rayui-select-box"></div>').insertAfter($(options.oElem));
            options.skin && options.$main.attr("skin", options.skin);
            options.$title = $('<div class="select-title"></div>').appendTo($(options.$main));
            options.elem = $('<div class="select-tree" style="max-height:' + globalOptions.maxHeight + 'px;"/>').appendTo($(options.$main));
            options.$value = $('<div class="select-value select-default">' + options.showTextOnNoSelected + '</div>').appendTo(options.$title);
            
            if (options.localSearch === true)
                options.$input = $('<input class="rayui-input select-input" placeholder="关键词"/>').appendTo(options.$title);
            options.$title.append('<span class="select-arrow"><i class="ra ra-arrow-down"></i></span>');

            $(options.oElem).hasClass("full-width") && options.$main.addClass("full-width");
            
            //初始化tree
            options.spread = options.spread || true;
            if (options.localSearch === true)
                options.localSearch = options.$input;
            if (options.url && options.onComplete) 
                    options.oOnComplete = options.onComplete;
            
            options.onComplete = function (result) {
                //result格式：ret,msg,data，把tree的数据data赋值给当前的options
                //注意区分本地数据和ajax数据
                !options.data && (options.data = options.tree.options.data);
                if (!options.isSetDefaultval) {
                    DealClass.utils.initSelectData.call(that);
                }
                typeof options.oOnComplete === "function" && options.oOnComplete(result);
            }
            options.tree = tree.render(options);
        },
        initSelectData: function () {
            var that = this,
                options = that.options,
                selectedValues = options.selectedValues,
                count = selectedValues.length;//数组

            options.selectedValues = [];
            options.selectedTextes = [];

            options.isSetDefaultval = true;

            if (count === 0) {
                options.$value.html(options.showTextOnNoSelected).addClass("select-default");
                return;
            }
            
            //默认值: [{ key: "name", value: "你好" }, { key: "id", value: 12 }]
            for (var i = 0; i < count; i++) {
                var key = selectedValues[i].key, val = selectedValues[i].value;
                DealClass.utils.select.call(that, key, val);
            }
        },
        setSelect: function () {
            var that = this,
                options = that.options,
                multiple = options.multiple,
                $select = $(options.oElem),
                $value = options.$value,
                vals = options.selectedValues;

            $value.html("").removeClass("select-default");
            $select.html("");

            if (multiple) {
                $.each(vals, function (a, b) {
                    $select.append('<option value="' + b + '" selected></option>');
                });
                $.each(options.selectedTextes, function (a, b) {
                    $value.append('<span class="tree-one-value">' + b + '<span class="tree-value-del" value="' + vals[a] + '"><i class="ra ra-wrong"></i></span></span>');
                });
            } else {
                if (vals.length > 0) {
                    $select.append('<option value="' + vals[0] + '" selected></option>');
                    $value.html(options.selectedTextes[0]);
                }
            }
            if (vals.length === 0 && options.showTextOnNoSelected !== "") {
                $value.html(options.showTextOnNoSelected).addClass("select-default");
            }
        },
        //tostate:false 不选中 true选中，默认true
        select: function (key, value, tostate) {
            var that = this,
                options = that.options,
                data, $li, curSelect;
            typeof tostate !== "boolean" && (tostate = true);
            if (value === undef) {
                value = key;
                key = options.fieldId;
            }
            if (key === options.fieldId) {
                $li = options.elem.find('li[data-id="' + value + '"]');
                curSelect = $li.hasClass("tree-selected");
                tostate !== curSelect && $li.find('>a').click();
            } else {
                var indexs, isFinded = false,
                    searchData = function (dd, iteration) {
                        $(dd).each(function (a, b) {
                            if (b[key] == value) {
                                indexs = iteration + a;
                                isFinded = true;
                                return false;
                            }
                            if (b.hasOwnProperty(options.fieldChildren))
                                searchData(b[options.fieldChildren], iteration + a + ",");
                            return true;
                        });
                    }

                data = options.data;
                searchData(data, "");
                if (isFinded) {
                    $li = options.elem.find('li[data-index="[' + indexs + ']"]');
                    curSelect = $li.hasClass("tree-selected");
                    tostate !== curSelect && $li.find('>a').click();
                }
            }
        },
        unselect: function (key, value) {
            var that = this,
                options = that.options;

            options.multiple
                ? DealClass.utils.select.call(that, key, value, false)
                : DealClass.utils.clearSelect.call(that);

        },
        clearSelect: function () {
            var that = this,
                options = that.options;
            //清除数据
            options.selectedValues = [];
            options.selectedTextes = [];
            //清除显示和select
            DealClass.utils.setSelect.call(that);
            //清除选中状态
            options.elem.find(".tree-selected").removeClass("tree-selected");
        },
        addEvents: function () {
            var that = this,
                options = that.options,
                multiple = options.multiple,
                $value = options.$value,
                showTree = function () {
                    //隐藏其他所有
                    rayui.toggleDocEvt();
                    //判断上面显示还是下面显示
                    var dataTreeHeight = options.elem.outerHeight(),
                        titleHeight = options.$title.outerHeight(),
                        blowHeight = $win.height() + $win.scrollTop() - options.$title.offset().top - titleHeight;
                    if (blowHeight < dataTreeHeight) {
                        //上面显示
                        options.$main.addClass("select-up");
                    } else {
                        options.$main.removeClass("select-up");
                    }

                    options.elem.slideDown(options.animSpeed, function () {
                        options.$main.addClass("select-expand");
                        if (options.localSearch) {
                            options.$input.focus();
                        }
                    });
                },
                hideTree = function () {

                    options.$main.removeClass("select-expand");
                    options.elem.css("display", "");
                    //options.elem.slideUp(options.animSpeed, function () {
                    //    options.$main.removeClass("select-expand");
                    //});
                };

            //点击事件
            options.$title.on("click." + plugName, function (e) {
                if (options.$main.hasClass("select-expand")) {
                    hideTree();
                } else {
                    showTree();
                }
                e.stopPropagation();
            });
            options.$main.on("click." + plugName, function(e) { e.stopPropagation(); });
            //li a点击事件
            options.tree.on("select", function (data, $li) {
                var value = data[options.fieldId],
                    showtxt = data[options.fieldName];
                if (options.selectDataType === "html") {
                    showtxt = $(this).html();
                } else if(options.selectDataType === "text") {
                    showtxt = $(this).text();
                }
                if (options.multiple) {
                    var index = options.selectedValues.indexOf(value);
                    if (index !== -1) {
                        options.selectedValues.splice(index, 1);
                        options.selectedTextes.splice(index, 1);
                        $li.removeClass("tree-selected");
                    } else {
                        options.selectedValues.push(value);
                        options.selectedTextes.push(showtxt);
                        $li.addClass("tree-selected");
                    }
                } else {
                    options.elem.find(".tree-selected").removeClass("tree-selected");
                    $li.addClass("tree-selected");
                    //如果是初次设置选中值，不隐藏
                    options.isSetDefaultval && hideTree();
                    options.selectedValues = [value];
                    options.selectedTextes = [showtxt];
                }
                DealClass.utils.setSelect.call(that);
                //回调
                typeof options.oOnSelect === "function" && options.oOnSelect.call(this, data, $li);
            });

            if (multiple) {
                //删除事件
                $value.on("click." + plugName, ".tree-value-del", function (e) {
                    e.stopPropagation();
                    var val = $(this).attr("value");
                    options.elem.find('li[data-id="' + val + '"]>a').click();
                    DealClass.utils.setSelect.call(that);
                });
                //设置默认显示值样式，模拟滚动条
                $value.height($value.parent().height() + 20)
                    .css("overflow-x", "auto")
                    .on("mousedown." + plugName, function (e) {
                        dict.$elem = $(this);
                        dict.X = e.clientX;
                        dict.needStop = false;
                        dict.left = $(this).scrollLeft();
                        e.preventDefault();
                        e.stopPropagation();
                    }).on("click." + plugName, function (e) {
                        //如果是滚动则阻止冒泡
                        if (dict.needStop) e.stopPropagation();
                    });
                if (!isDocBindMouseEvent) {
                    isDocBindMouseEvent = true;
                    $doc.on("mousemove." + plugName, function (e) {
                        if (dict.X > -1) {
                            dict.needStop = true;
                            dict.$elem.scrollLeft(dict.X - e.clientX + dict.left);
                        }
                    }).on("mouseup." + plugName, function () {
                        if (dict.X > -1) {
                            dict.X = -1;
                        };
                    });
                }
            }

            //这里不能使用options.localSearch === true，因为options.localSearch已经发生了变化，变成jquery对象
            if (options.localSearch) {
                options.$input.on("keyup." + plugName, function () {
                    $.each(options.selectedValues, function (a, b) {
                        options.elem.find('li[data-id="' + b + '"]').addClass("tree-selected");
                    });
                }).on("click." + plugName, function (e) { e.stopPropagation(); });
            }
        },
        on: function (event, func) {
            if (typeof event !== "string" || typeof func !== "function") return;
            var that = this,
                options = that.options;

            switch (event) {
                //点击
                case "select": options.oOnSelect = func; break;
                //其他
                default: options.tree.on.call(options.tree, event, func); break;
            }
        }
    }

    DealClass.prototype = {
        on: function (event, callback) {
            DealClass.utils.on.call(this, event, callback);
			return this;
        },
        search: function (str) {
            var tree = this.options.tree;
            tree.search.call(tree, str);
			return this;
        },
        reload: function (options) {
            var tree = this.options.tree;
            tree.reload.call(tree, options);
			return this;
        },
        select: function (key, value) {
            DealClass.utils.select.call(this, key, value);
			return this;
        },
        unselect: function (key, value) {
            DealClass.utils.unselect.call(this, key, value);
			return this;
        },
        clearSelect: function () {
            DealClass.utils.clearSelect.call(this);
			return this;
        },
        setWidth: function (w) {
            var tree = this.options.tree;
            tree.setWidth.call(tree, w);
			return this;
        },
        setHeight: function (h) {
            var options = this.options;
            options.elem.css({
                "max-height": "",
                height: h + "px"
            });
			return this;
        },
        setWidthHeight: function (w, h) {
            var options = this.options,
                tree = options.tree;
            tree.setWidth.call(tree, w);
            options.elem.css({
                "max-height": "",
                height: h + "px"
            });
			return this;
        }
    }

    !rayui.select && rayui.bindDocEvt(plugName, function () {
        $(".select-expand .select-tree").css("display", "");
        $(".select-expand").removeClass("select-expand");
    });

    var selecttree = {
        options: globalOptions,
        render: function (options) {
            var obj = options.elem;
            if ($(obj).length === 0) return "DOM对象不存在";

            var cc = new DealClass(options);
            dataCache.mclass[globalIndex++] = cc;
            return cc;
        }
    };
    
    exports(plugName, selecttree);
}, rayui.jsAsync());
